﻿using System;
using System.Collections;
using System.Drawing;
using System.Timers;

namespace 贪吃蛇试玩demo
{
    class Palette //调色板还行
    {
        private int _width = 20; //宽度
        private int _height = 20; //高度
        private Color _bgcolor; //背景色
        private Graphics _gpPalette; //画布
        public ArrayList _blocks; //蛇身
        public Direction _direction; //前进方向（全局可用）
        public Timer timerBlock; //更新器（全局可用）
        private Block _food; //当前食物
        private int _size = 20; //方块大小
        public int _level = 1; //速度等级
        public bool _isGameOver = false; //游戏是否结束（全局可用）
        private int[] _speed = new int[] { 500, 450, 400, 350, 300, 250, 200, 150, 100, 100, 50 }; //游戏速度

        public Palette(int width,int height,int size,Color bgColor,Graphics g,int lvl) //定义初始宽度、高度、方块大小、背景色、画布、等级
        {
            this._width = width; //宽度
            this._height = height; //高度
            this._bgcolor = bgColor; //背景色
            this._gpPalette = g; //画布
            this._size = size; //方块大小
            this._level = lvl; //速度等级
            this._blocks = new ArrayList(); //生成蛇（声明一个动态数组）
            this._blocks.Insert(0, (new Block(Color.Red, this._size, new Point(width / 2, height / 2)))); //插入第一个数据，生成新的方块颜色红，方块大小为_size（20），位置在中间{（高度\宽度）/2取整} （插入2个值到数组）
            this._direction = Direction.Right; //初始方向向右
        }

        public void Start() //定义开始方法（全局，开始游戏、设定食物、设定触发器）
        {
            this._food = GetFood(); //生成随机食物（调用生成食物的方法）

            timerBlock = new System.Timers.Timer(_speed[this._level]); //把更新器实例化（_speed[._level]毫秒更新一次，调用系统自带的更新器类）
            timerBlock.Elapsed += new System.Timers.ElapsedEventHandler(OnBlockTimedEvent); //到达时间后执行OnBlockTimedEvent（_speed[._level]毫秒后执行OnBlockTimedEvent）
            timerBlock.AutoReset = true; //只执行一次（false为一直执行）
            timerBlock.Start(); //启动
            //timer.Enabled = true

            //需要调用 timer.Start()或者timer.Enabled = true来启动它， timer.Start()的内部原理还是设置timer.Enabled = true;  

            //调用 timer.Stop()或者timer.Enabled = false来停止引发Elapsed事件， timer.Stop()的内部原理还是设置timer.Enabled = false，  

            //最重要的是timer.Enabled = false后会取消线程池中当前等待队列中剩余任务的执行。  
        }

        //更新
        private void OnBlockTimedEvent(object ource,ElapsedEventArgs e) //计时器的执行函数
        {
            this.Move(); //更新蛇的坐标（调用Move方法）
            if (this.CheckDead())
            {
                this.timerBlock.Stop();
                this.timerBlock.Dispose();
                System.Windows.Forms.MessageBox.Show("你总共吃掉了: " + ((int)this._blocks.Count-1) + "个食物", "Game Over");
            }
        }

        private bool CheckDead() //检测游戏是否结束的方法
        {
            //int 长度 = this._size;
            //int 满屏 = FormMain.页面大小 * FormMain.页面大小;
            if (this._size >= FormMain.页面大小 * FormMain.页面大小) //通关
            {
                //this.timerBlock.Stop(); //停止执行触发器
                //this.timerBlock.Dispose(); //释放触发器的所有资源
                this._isGameOver = true; //游戏结束
                System.Windows.Forms.MessageBox.Show("恭喜你通关了！", "Game Over"); //弹出提示
                return true; //返回为真
            }

            Block head = (Block)(this._blocks[0]); //取蛇头一块的位置

            if (head.Point.X < 0 || head.Point.Y < 0 || head.Point.X >= this._width || head.Point.Y >= this._height) //检测蛇头是否越过边界
            {
                this._isGameOver = true; //游戏结束
                return true; //返回为真
            }
            for(int i = 1; i < this._blocks.Count; i++) //检测蛇头和所有身体
            {
                Block b = (Block)this._blocks[i]; //取一块身体
                if (head.Point.X == b.Point.X && head.Point.Y == b.Point.Y) //检测是否有重合
                {
                    this._isGameOver = true; //游戏结束
                    return true; //返回为真
                }
            }
            this._isGameOver = false; //游戏继续
            return false; //返回为假
        }

        private Block GetFood() //生成食物
        {
            Block food = null; //删掉食物
            Random r = new Random(); //生成随机数
            bool redo = false; //定义是否成立的变量
            while (true) //无限循环
            {
                redo = false; //先定义为成立
                int x = r.Next(this._width); //生成食物的随机x坐标
                int y = r.Next(this._height); //生成食物的随机y坐标
                for (int i = 0; i < this._blocks.Count; i++) //判断食物与所有蛇部位是否重合
                {
                    Block b = (Block)(this._blocks[i]); //分别取蛇的部位
                    if (b.Point.X == x && b.Point.Y == y) //判断是否重合
                    {
                        redo = true; //重合输出真
                    }
                }
                if (redo == false) //redo为真时重复执行
                {
                    food = new Block(Color.Black, this._size, new Point(x, y)); //不重合输出食物
                    break; //跳出循环
                }
            }
            return food; //返回食物坐标
        }

        private void Move() //更新坐标的方法
        {
            Point p;
            Block head = (Block)(this._blocks[0]);
            if (this._direction == Direction.Up)
            {
                p = new Point(head.Point.X, head.Point.Y
                    - 1);
            }
            else if (this._direction == Direction.Down)
            {
                p = new Point(head.Point.X, head.Point.Y
                    + 1);
            }
            else if (this._direction == Direction.Left)
            {
                p = new Point(head.Point.X - 1, head.Point.Y);
            }
            else
            {
                p = new Point(head.Point.X + 1, head.Point.Y);
            };

            Block b = new Block(Color.Red, this._size, p);

            if (this._food.Point != p)
            {
                this._blocks.RemoveAt(this._blocks.Count - 1);
            }
            else
            {
                this._food = this.GetFood();
            }

            this._blocks.Insert(0, b);

            this.PaintPalette(this._gpPalette);

            if (this._level < 11) {
                int 长度 = this._size;
                if (长度 >= 10 && 升级 != true && 停止 == false)
                {
                    停止= true;
                    加速();
                }
                if (升级)
                {
                    this.timerBlock.Stop();
                    this.timerBlock.Dispose();
                    this._level += 1;
                    timerBlock = new System.Timers.Timer(_speed[this._level]);
                    timerBlock.Elapsed += new System.Timers.ElapsedEventHandler(OnBlockTimedEvent);
                    timerBlock.AutoReset = true;
                    timerBlock.Start();
                    升级 = false;
                }
            }
        }

        static public bool 停止 = false;
        static public bool 升级 = false;
        public void 加速()
        {
            System.Timers.Timer t = new System.Timers.Timer(20000);//实例化Timer类，设置间隔时间为20秒；

            t.Elapsed += new System.Timers.ElapsedEventHandler(提速);//到达时间的时候执行事件；

            t.AutoReset = true;//设置是执行一次（false）还是一直执行(true)；

            t.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件；
        }
        public void 提速(object ource, ElapsedEventArgs e)
        {
            升级 = true;

        }

        public void PaintPalette(Graphics gp)
        {
            gp.Clear(this._bgcolor);
            this._food.Paint(gp);
            foreach (Block b in this._blocks)
                b.Paint(gp);
        }


    }

    public enum Direction
    {
        Left,
        Right,
        Up,
        Down
    }
}
